FIT2-2022b 第05回 リスト
前回授業の復習
ballとPadの接触判定
計算簡略化のため、ballは「10x10の正方形」と解釈
ball, padそれぞれの上下左右端のx,y座標は以下のように計算可能
表記簡素化のため、blx(Ball Left X), bty (Ball Top Y) のように命名
https://gyazo.com/e87c4f7e3677c802666edf7d0729bff3
「接触している状態」を判定式に落とすと…以下4条件の複合状態と言える
https://gyazo.com/cc4d247c4f6a0e016ca80300f7ee4878
結論こうなる
code:python
import pyxel
# 中略 #
def update():
# 中略 #
# ボールの上下左右座標を取得 (正方形と仮定)
bxl = ballx - 10
bxr = ballx + 10
byt = bally - 10
byb = bally + 10
# パッドの上下左右座標を取得
pxl = padx - 20
pxr = padx + 20
pyt = 195
pyb = 200
# ボールの左右端がpadの左右幅に入っているかどうか
if pxl <= bxr and bxl <= pxr:
# ボールの上下端がpadの上下幅に入っているかどうか
if pyt <= byb and byt <= pyb:
# キャッチ成功なのでスコアを増やす
score += 100
# 接触後すぐにボールを上に戻さないとスコアが増え続けるのでリセット処理
ballx = 100
bally = 0
speed = speed + 1
# padに接触せずとも下辺に到達したらボールを上に戻す
if bally >= 200:
ballx = 100
bally = 0
speed = speed + 1
# 後略 #
簡単にするなら以下でも一応良い
ballは中心座標のx,yのみを意識 (円周がpadと接触するだけではNGとする)
code:python
if padx - 20 <= ballx < padx + 20 and 195 < bally:
# 接触したということにする
ランダムな開始位置と移動確度
pyxel.randi(0, 100) のように random integer (ランダムな整数) を生成することが可能
この書き方の場合、0~100のうち、ランダムな整数が生成される
code:python
bally = 0 # 上下位置は必ず上辺から
angle = pyxel.randi(30, 150) # ボールを動かす角度を30~150でランダムに
vx = pyxel.cos(angle) # 角度angleで長さ1進めたい場合のx方向移動量
vy = pyxel.sin(angle) # 角度angleで長さ1進めたい場合のy方向移動量
余談:再利用する処理こそ関数に!
code:python
def reset_ball():
global ballx, bally, vx, vy
ballx = pyxel.rndi(0, 199)
bally = 0
angle = pyxel.rndi(30, 150)
vx = pyxel.cos(angle)
vy = pyxel.sin(angle)
## 中略 ##
pyxel.init(200, 200)
reset_ball()
## 中略 ##
def update():
## 中略 ##
if ballとpadが接触した:
score += 100
reset_ball()
if bally >= 200:
reset_ball()
本日の講義
https://gyazo.com/ecf74ba692a220c498685dda48bfd957
複数のボールを同時に扱う処理を通じて「リスト」の概念を復習します
加えてミニプロの詳細説明
現状授業進捗の最新コードを以下に張っておきます
code:python
import pyxel
pyxel.init(200,200)
speed = 3
padx = 100
score = 0
ballx = pyxel.rndi(0,199)
bally = 0
angle = pyxel.rndi(30,150)
vx = pyxel.cos(angle)
vy = pyxel.sin(angle)
def update():
global ballx, bally, vx, vy, padx, speed, score
# ballとpadの場所を最新化
ballx += vx * speed
bally += vy * speed
padx = pyxel.mouse_x
# ボールが左右の壁に当たったら、x軸の移動方向を反転
if ballx <= 0 or 200 <= ballx:
vx = vx * -1
# ボールの上下左右座標を取得 (正方形と仮定)
bxl = ballx - 10
bxr = ballx + 10
byt = bally - 10
byb = bally + 10
pxl = padx - 20
pxr = padx + 20
pyt = 195
pyb = 200
# ボールの左右端がpadの左右幅に入っているかどうか
if pxl <= bxr and bxl <= pxr:
# ボールの上下端がpadの上下幅に入っているかどうか
if pyt <= byb and byt <= pyb:
# キャッチ成功
score += 100
# 接触後すぐにボールを上に戻さないとスコアが増え続ける
ballx = pyxel.rndi(0,199)
bally = 0
angle = pyxel.rndi(30,150)
vx = pyxel.cos(angle)
vy = pyxel.sin(angle)
elif bally >= 200:
# padに接触せずとも下辺に到達したらボールを上に戻す
ballx = pyxel.rndi(0,199)
bally = 0
angle = pyxel.rndi(30,150)
vx = pyxel.cos(angle)
vy = pyxel.sin(angle)
def draw():
global ballx, bally, padx, score
pyxel.cls(7)
pyxel.circ(ballx, bally, 10, 6)
pyxel.rect(padx-20, 195, 40, 5, 14)
pyxel.text(0, 0, str(score), 0)
pyxel.run(update, draw)
【成績】そろそろ何を作るかを考え始めよう
今まで教えたこと
画面描画
「接触判定」という考え方
リスト
残り教えるのは以下のみ
コードの可読性/保守性を上げるための「オブジェクト」「関数定義」
サンプルとして概念を追加解説できるやつ
横スクロールゲーム (jump_game.py)
俯瞰型2dゲーム (パックマン、ゼルダの冒険)
ボードゲーム (すごろく、オセロ)
今まで教えた内容で出来ること
wasdでダンジョン内を移動するゲーム
code:python
import pyxel
# 10x10のマップを二重配列で定義
map = [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 9, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, # mapの各数字が何に該当するかを定義
field = 0
block = 9
character = 1
# キャラクターのx,y座標
char_x = 5
char_y = 5
# mapを10x10にしたので、1マスの縦横幅は20
cell_width = 20
def update():
global char_x, char_y
# WASDでキャラクター移動 and 移動先がblockだったら移動キャンセル
char_x -= 1
char_y += 1
char_x += 1
char_y -= 1
def draw():
pyxel.cls(7)
# マップを描画
for x, row in enumerate(map):
for y, cell in enumerate(row):
color = 7
if cell == block:
color = 0
pyxel.rect(x * cell_width, y * cell_width, cell_width, cell_width, color)
# キャラクターを描画
pyxel.rect(char_x * cell_width, char_y * cell_width, cell_width, cell_width, 5)
pyxel.init(200, 200)
pyxel.run(update, draw)
https://gyazo.com/744ac606303dd4fa18a40592e4a68773